﻿using System;
using System.Reflection;
using System.Reflection.Emit;

namespace Aeon.Emulator.Decoding.Recompiler.StringCompilers
{
    /// <summary>
    /// Generates IL for emulating a CMPS instruction.
    /// </summary>
    internal sealed class CmpsCompiler : StringBase
    {
        private static readonly MethodInfo CmpByte = typeof(Instructions.Cmp).GetMethod("ByteCompare", BindingFlags.Static | BindingFlags.Public);
        private static readonly MethodInfo CmpWord = typeof(Instructions.Cmp).GetMethod("WordCompare", BindingFlags.Static | BindingFlags.Public);
        private static readonly MethodInfo CmpDWord = typeof(Instructions.Cmp).GetMethod("DWordCompare", BindingFlags.Static | BindingFlags.Public);

        /// <summary>
        /// Initializes a new instance of the CmpsCompiler class.
        /// </summary>
        /// <param name="registers">Associated register expression generator.</param>
        public CmpsCompiler(RegisterExpressions registers)
            : base(registers, true)
        {
        }

        /// <summary>
        /// Generates the IL for one iteration of the instruction.
        /// </summary>
        protected override void GenerateIteration()
        {
            LoadVirtualMachine();
            GenerateDS_SI();
            GenerateES_DI(null);

            if(this.OperandSize == 32)
                this.IL.Emit(OpCodes.Call, CmpDWord);
            else if(this.OperandSize == 16)
                this.IL.Emit(OpCodes.Call, CmpWord);
            else if(this.OperandSize == 8)
                this.IL.Emit(OpCodes.Call, CmpByte);
            else
                throw new InvalidOperationException();

            IncrementSI();
            IncrementDI();
        }
    }
}
